#!/usr/bin/python
# -*- coding: utf-8 -*-
import threading
import QueryBox
import time
import os, sys
import gobject

class Updater(object):
    def __init__(self, model, eventList, add, delete, cancel, start, resetId):
        self.thread = Uthread(self.__run)
        self.thread2 = Uthread(self.__run2)
        self.model = model
        self.eventList = eventList
        self.add = add
        self.delete = delete
        self.cancel = cancel
        self.restart = start
        self.resetId = resetId
        self.queryBox = QueryBox.QueryBox()
        self.toUpdate = []
        self.upMap = {}
        self.stop = False
    
    def setEmail(self, gmail):
        self.queryBox.setEmail(gmail)
        
    def stopUpdater(self):
        if self.thread.isAlive() or self.thread2.isAlive():
            self.stop = True
            self.thread.join()
            self.thread2.join()
            self.stop = False
        self.thread = Uthread(self.__run)
        self.thread2 = Uthread(self.__run2)
    
    def start(self):
        self.stopUpdater()
        self.thread.daemon = True
        self.thread2.daemon = True
        self.thread.start()
        self.thread2.start()
        
    def addDownload(self, url):
        return self.queryBox.add(url)
        
    def __run2(self):
        while not self.stop:
            self.__checkEvent()
            time.sleep(2)
        
    def __run(self):
        while not self.stop:
            self.upMap = self.queryBox.getUpdate()
            gobject.idle_add(self.__sequential)
            time.sleep(10)
    
    def __sequential(self):
        print>>sys.stderr, "___sequential"
        if self.upMap:
            toDelete = []
            self.model.foreach(self.__checkInner, toDelete)
        print>>sys.stderr, "__sequential delete"
        lock = threading.Lock()
        lock.acquire()
        for i in toDelete:
            self.delete(i[0], i[1])
        lock.release()
        del toDelete
        print>>sys.stderr, "___sequential ckOut"
        if self.upMap:
            self.__checkOuter()
        print>>sys.stderr, "___sequential clear"
        self.upMap.clear()
        print self.toUpdate   
        print>>sys.stderr, "___sequential updat"
        if self.toUpdate:
            self.queryBox.notify(self.toUpdate)
            self.toUpdate = []         
        print>>sys.stderr, "___sequential done"
    
    def __checkInner(self, model, path, iter, toDelete):
        print>>sys.stderr, "__checkInner"
        id, url, status, percentage = model.get(iter, 0, 1, 4, 5)
        percent = float(percentage.split('%')[0])
        if self.upMap.has_key(id):
            tmpStatus = self.upMap[id]['status']
            if tmpStatus == 'delete':
                toDelete.append([id, self.model.get_iter(path)])
            elif tmpStatus == 'download' and self.upMap[id]['progress'] != percent:
                self.toUpdate.append({'id':id, 'status':status, 'progress':percent})
            elif status != tmpStatus:
                if tmpStatus == 'done' or (tmpStatus == 'queue' and status != 'cancel') or tmpStatus == 'download':
                    self.toUpdate.append({'id':id, 'status':status, 'progress':percent})                
                elif tmpStatus == 'cancel':
                    self.cancel(None, model, iter)
                elif tmpStatus == 'fail':
                    model.set_value(iter, 4, 'fail')
                elif tmpStatus == 'queue':
                    self.restart(None, self.model, self.model.get_iter(path))
                    self.toUpdate.append({'id':id, 'status':'download', 'progress':0.0})
            self.upMap.pop(id)
        elif (status == 'download' or status == 'done') and percent > 0.0:
            self.toUpdate.append({'id':id, 'status':status, 'progress':percent})
        print>>sys.stderr, "___checkInner done"
            #print id, url, status, percent
            # only when addList is set should we handle this
            #id = self.queryBox.add(url)
            #gobject.idle_add(self.resetId, iter, id)
            #toUpdate.append({'id':id, 'status':status, 'progress':percent})
    
    def __checkOuter(self):
        print>>sys.stderr, "__checkOuter"
        for i in self.upMap.itervalues():
            if i['status'] == 'queue' or i['status'] == 'download':
                self.add(i['id'], i['url'])
                self.toUpdate.append({'id':i['id'], 'status':'download', 'progress':0.0})
            elif i['status'] != 'delete':
                self.add(i['id'], i['url'], i['status'], str(int(i['progress']))+'%')
        print>>sys.stderr, "___checkOuter done"
    
    def __checkEvent(self):
        print>>sys.stderr, "__checkEvent"
        if self.eventList:
            #print self.eventList, 'eventList'
            #self.queryBox.notify(self.eventList)
            # safe pop
            gobject.idle_add(self.notifyAndPop, self.eventList)
                
    def notifyAndPop(self, topop):
        self.queryBox.notify(self.eventList)
        while self.eventList:
            self.eventList.pop()
                
class Uthread(threading.Thread):
    def __init__(self, runner):
        super(Uthread, self).__init__()
        self.runner = runner
        
    def run(self):
        self.runner()
        
                
